package com.moli.iov.handle.alarm.biz.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.moli.iov.handle.alarm.constants.Constant;
import com.moli.iov.handle.alarm.enums.AlarmCodeStatusEnum;
import com.moli.iov.handle.alarm.model.dto.AlarmOnLineDto;
import com.moli.iov.handle.alarm.model.po.extend.FenceInfoExtend;
import com.moli.iov.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 报警业务工具
 * </p>
 *
 * @author: zql
 * @Date: 2019/2/15 15:22
 */
@Slf4j
@Component
public class AlarmUtils {

  @Autowired
  private BaseAlarmUtils baseAlarmUtils;

  /**
   * 离线报警时长
   */
  @Value("${OFF_LINE_TIME}")
  private long offLineTime;

  /**
   * 获取缓存数据
   */
  public String get(String key) {
    return baseAlarmUtils.get(key);
  }

  /**
   * 设置 取消报警 数量
   */
  public void setAlarmOff(String vin,
      int alarmCode,
      int num) {

    baseAlarmUtils.setAlarmCout(vin,
        alarmCode,
        String.valueOf(num),
        Constant.ALARM_FIELD_OFF);
  }

  /**
   * 初始化取消报警防抖 数量
   */
  public void initAlarmOffTimes(String vin,
      int alarmCode) {

    int alarmOffTimes = getAlarmOff(vin, alarmCode);

    if (alarmOffTimes > Constant.ANTI_SHAKE_NON) {

      setAlarmOff(vin,
          alarmCode,
          Constant.ANTI_SHAKE_NON);
    }
  }

  /**
   * 设置 报警 数量
   */
  public void setAlarmOn(String vin,
      int alarmCode,
      int num) {

    baseAlarmUtils.setAlarmCout(vin,
        alarmCode,
        String.valueOf(num),
        Constant.ALARM_FIELD_ON);
  }

  /**
   * 初始化报警防抖 数量
   */
  public void initAlarmOnTimes(String vin,
      int alarmCode) {

    int alarmTimes = getAlarmOn(vin,
        alarmCode);

    if (alarmTimes > Constant.ANTI_SHAKE_NON) {

      setAlarmOn(vin,
          alarmCode,
          Constant.ANTI_SHAKE_NON);
    }


  }

  /**
   * 报警数量增加 num 防抖用
   */
  public long incrtAlarmOn(String vin,
      int alarmCode,
      int num) {

    return baseAlarmUtils.incrtAlarm(vin,
        alarmCode,
        num,
        Constant.ALARM_FIELD_ON);
  }

  /**
   * 取消报警数量 增加 num 防抖用
   */
  public long incrtAlarmOff(String vin,
      int alarmCode,
      int num) {

    return baseAlarmUtils.incrtAlarm(vin,
        alarmCode,
        num,
        Constant.ALARM_FIELD_OFF);
  }

  /**
   * 获取当前报警数量
   */
  public int getAlarmOn(String vin,
      int alarmCode) {

    return baseAlarmUtils.getAlarmCount(vin,
        alarmCode,
        Constant.ALARM_FIELD_ON);
  }

  /**
   * 获取当前取消报警数量
   */
  public int getAlarmOff(String vin,
      int alarmCode) {

    return baseAlarmUtils.getAlarmCount(vin,
        alarmCode,
        Constant.ALARM_FIELD_OFF);
  }

  /**
   * 缓存当前报警类型的状态：true、正在报警  false、报警取消
   */
  public void setAlarmCodeStatus(String vin,
      int alarmCode,
      boolean isAlarming) {

    baseAlarmUtils.setAlarmCodeStatus(vin,
        alarmCode,
        isAlarming);
  }

  /**
   * 判断 当前报警类型 是否正在报警
   */
  public boolean isAlarming(String vin,
      int alarmCode) {

    String alarmCodeStatusStr =
        baseAlarmUtils.getAlarmCodeStatus(vin, alarmCode);

    if (StringUtil.isBlank(alarmCodeStatusStr)) {

      return AlarmCodeStatusEnum.ALARM_CANCELLED.getFlag();
    }

    return Boolean.parseBoolean(alarmCodeStatusStr);
  }

  /**
   * 添加 离线集合
   */
  public void setOffLine(AlarmOnLineDto alarmOnLineDto) {

    baseAlarmUtils.setOffLine(alarmOnLineDto);
  }

  /**
   * 获取离线车辆列表
   */
  public List<AlarmOnLineDto> getOffLineList() {

    Map map = baseAlarmUtils.getOffLineMap();
    List<AlarmOnLineDto> alarmOnLineDtos = new ArrayList<>();

    map.forEach((key, val) -> {
      try {
        if (val == null) {
          return;
        }

        alarmOnLineDtos.add(JSON.parseObject(val.toString(), AlarmOnLineDto.class));
      } catch (Exception e) {
        log.error("获取离线车辆列表异常", e);
      }
    });
    return alarmOnLineDtos;
  }

  /**
   * 恢复在线 或 已生成报警信息则 移除离线集合数据
   */
  public long deleteOffLineByVin(String vin) {
    log.info("移除离线集合数据 vin：{}", vin);
    return baseAlarmUtils.deleteOffLine(vin);
  }

  /**
   * 获取超里程阀值
   */
  public double getThresholdMileageOfCache(String vin) {
    String thresholdMileageStr = baseAlarmUtils.get(getKey(vin));
    if (StringUtil.isNotBlank(thresholdMileageStr)) {
      return Double.parseDouble(thresholdMileageStr);
    }

    return Constant.THRESHOLD_MILEAGE_NON;
  }

  /**
   * 设置里程阀值
   */
  public void setThresholdMileage(String vin, String thresholdMileage) {
    baseAlarmUtils.set(getKey(vin), thresholdMileage);
  }

  /**
   * 获取里程阀值key
   */
  private String getKey(String vin) {
    return Constant.THRESHOLD_MILEAGE + vin;
  }

  /**
   * 获取忽略告警缓存信息
   */
  public String getIgnoreAlarm(String key, Integer code) {
    return get(getIgnoreKey(key, code));
  }


  /**
   * 删除忽略报警信息
   * @param key
   * @param code
   */
  public void deleteIgnoreAlarm(String key, Integer code){
    baseAlarmUtils.delete(getIgnoreKey(key, code));
  }
  /**
   * 获取忽略告警key
   */
  private String getIgnoreKey(String key, Integer code) {
    return Constant.IGNORE_ALARM + key + ":" + code;
  }

  /**
   * 设置车辆绑定/所处的围栏
   */
  public void setVehicleFence(String vin, FenceInfoExtend fenceInfoExtend) {
    baseAlarmUtils
        .set(Constant.VEHICLE_BINDING_FENCE_KEY + vin, JSONObject.toJSONString(fenceInfoExtend));
  }

  /**
   * 如果和redis致则更新
   */
  public void setVehicleFenceIfNon(String vin, FenceInfoExtend fenceInfoExtend) {
    String vfStr = getVehicleFence(vin);
    if (StringUtil.isBlank(vfStr)) {
      setVehicleFence(vin, fenceInfoExtend);
      return;
    }

    FenceInfoExtend fenceInfoExtend1 = JSONObject.parseObject(vfStr, FenceInfoExtend.class);
    if (!fenceInfoExtend.getFenceId().equals(fenceInfoExtend1.getFenceId())) {
      setVehicleFence(vin, fenceInfoExtend);
    }
  }

  /**
   * 获取车辆所处的围栏
   */
  public String getVehicleFence(String vin) {
    return baseAlarmUtils.get(Constant.VEHICLE_BINDING_FENCE_KEY + vin);
  }
}
